How to Iterate Complex Structures in Pipelines as Code - Dictionary or List Sprig functions
Introduction
Pipelines as Code (PaC) is a pivotal feature, enabling intricate Spinnaker pipelines' rapid and efficient provisioning. By strategically utilizing Dinghyfiles, we can apply the same PaC code across multiple applications, thereby significantly curtailing development timelines and bolstering the efficiency of Continuous Deployment workflows. As complexity mounts, Dinghyfiles evolve into sophisticated constructs, warranting a comprehensive understanding of their potential. This article exemplifies the extensive capabilities of iterating over intricate data types during pipeline provisioning.
Prerequisites
- Pipelines as Code plugin/service available in Spinnaker (Installation and configuration instructions available here)
- ARM-CLI used for debugging purposes and validation - ARM-CLI
Instructions
In this example, we are configuring a pipeline with two distinct stages designated for the Development (Dev) and Quality Assurance (QA) environments.
Both stages share a common definition to optimize resource utilization. This is achieved by employing a wait module
for stage provisioning. To maintain code abstraction and reduce the Dinghyfile's size, module parameters are provisioned from a parameter dictionary, which is iterated using a List aggregator.
For simplicity, we will utilize a wait module.
- The wait module is defined as follows:
{
"name": "{{ var "waitname" ?: "defaultname" }}",
"type": "wait",
"waitTime": {{ var "waitTime" ?: 100 }}
}
-
As depicted above, the module expects two variables:
waitname
andwaitTime
. In the absence of these variables,defaultname
is assumed forwaitname
, and100
forwaitTime
. -
Within the main Dinghyfile, the code appears as follows:
{
"application": "dictrangeexample",
"pipelines": [
{
"name": "Loop Example",
"application": "dictrangeexample",
"stages": [
{{ $dictdev := dict "waitTime" "11" "name" "dev" }}
{{ $dictqa := dict "waitTime" "21" "name" "qa" }}
{{ $myenvs := list $dictdev $dictqa }}
{{ $count := 1 }}
{{ range $myenvs }}
{{ module "dinghy-modules/wait.stage.module" "waitname" ( get . "name" ) "waitTime" ( get . "waitTime" ) }}
{{ if ne $count (len $myenvs) }}
{{ $count = add $count 1 }}
,
{{ end }}
{{ end }}
]
}
]
}
-
We initialize two dictionary variables, one holding parameters for the Dev environment stage and the other for the QA environment stage. Subsequently, we consolidate the two dictionaries into a new list variable for iterative processing. We also establish a counter to track the current iteration index to maintain clarity. Once the dictionaries are unified into a list, we iterate over the list structure using the 'range' construct, as demonstrated above.
-
Within the loop, we dynamically render the wait module with the dictionary parameters, utilizing the syntax
(get . "field")
. Here,.
denotes the current iterated object, andget
retrieves the specified field, in this case,name
andwaitTime
. -
In this example, we have successfully generated a pipeline with customized parameters for two stages, targeting distinct environments.
Please note that while the ARM-CLI 2.3.0 may flag the above syntax as potentially problematic, Spinnaker successfully interprets the code and provisions the pipeline.